import logging
import re
from typing import Optional

import chat
from llm import LLM

# --- 配置 ---
logging.basicConfig(format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
                    datefmt="%Y-%m-%d %H:%M:%S",
                    level=logging.INFO)
logger = logging.getLogger(__name__)


# --- 主要分类函数 ---


# 在文件顶部定义全局变量
llm = LLM("qwen3_32")
config = llm.get_config()

MODEL = config['modelname']
MODEL_CONTEXT_WINDOW = config['context_window']
MODEL_INPUT_WINDOW = MODEL_CONTEXT_WINDOW // 2


def classify_text(text_content: str, classify: str) -> Optional[str]:
    """
    调用 chat.py 中的 API 函数进行文本分类。
    """
    # 1. 构建与之前完全相同的提示词
    prompt = f"""/no_think 任务：对输入文本进行分类
    请严格按照以下步骤处理：
    1. 仔细阅读以下待分类文本
    2. 从提供的可用类别列表中选择**唯一最匹配**的类别名称进行分类
    3. **只输出类别名称本身**，不要添加任何解释、标点或格式

    可用类别列表：
    {classify}

    待分类文本：
    内容：{text_content}

    请确保输出仅包含列表中的准确类别名称，格式示例：'类别名称'"""

    # 2. 将提示词封装成 API 需要的 messages 格式
    messages = [{"role": "user", "content": prompt}]

    try:
        # 3. 调用 chat.py 中的非流式 API 函数
        # chat.call_llm_api 在 stream=False 时直接返回解析后的字典
        response_dict = chat.call_llm_api(messages, stream=False)

        if not response_dict:
            logger.error("classify：从 chat.call_llm_api 未收到有效响应。")
            return "错误：分类服务调用失败"

        # 4. 从返回的字典中提取模型生成的内容
        raw_response = response_dict.get("choices", [{}])[0].get("message", {}).get("content", "")
        logger.info(f"原始响应：'{raw_response}'")

        if not raw_response:
            return "未知"

        # 5. 执行与之前完全相同的清洗逻辑
        cleaned_response = re.sub(r'[^\w\u4e00-\u9fa5/]', '', raw_response.strip())
        cleaned_response = re.sub(r'\s+', '', cleaned_response)
        cleaned_response = cleaned_response.replace('think/think', '')

        return cleaned_response

    except Exception as e:
        logger.error(f"classify：调用LLM进行分类时出错: {e}", exc_info=True)
        return "错误：分类时发生服务器内部错误"



# 模型处理全文信息
def extract_key_words(text, max_length=3000, max_keywords=15):
    """
    从文本中提取最能体现文章内容的关键词或摘要主旨词

    Args:
        text: 输入的论文文章内容
        max_keywords: 最大关键词数量，默认15个

    Returns:
        str: 逗号分隔的关键词字符串
    """
    essay_title = ''
    # 分割文章标题
    if '#' in text:
        parts = text.split('#', 1)  # 只分割第一个#
        essay_title = parts[0].strip() if(len(parts) == 2) else ''

    logger.info(f"输入的论文标题为：'{essay_title}'")
    # 去除特殊字符，保留中文、英文、数字
    text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9\s]', ' ', text)
    # 去除多余空格
    text = re.sub(r'\s+', ' ', text).strip()

    # 如果文本过长，先进行截取
    if len(text) > max_length:
        # 处理文本过长问题，截取前1000个字符以及后500个字符
        text = text[:1000] + text[-500:]

    essay_prompt = f"""
    你是专业的学术论文关键词提取系统，请严格按照学术领域要求提取关键词。

    任务：从以下学术论文中提取{max_keywords}个最能体现文章核心内容的关键词

    质量要求：
    1. 优先提取复合术语（2-5个字的词组）
    2. 确保是对应领域专业词汇
    3. 按在文中重要性排序
    4. 严格去重（完全相同字符串只保留一个）

    输出格式：仅返回逗号分隔的字符串，如：机器学习,神经网络,TCP协议,微服务架构,API接口,吞吐量,延迟指标,ISO标准,安全协议,负载均衡

    学术论文：
    {text}

    请返回提取的关键词：
    """

    try:
        extract_key_words = llm.generate_response(essay_prompt)
        logger.info(f"提取到的专有名词为：'{extract_key_words}'")

        return essay_title + "," + extract_key_words
    except Exception as e:
        # 如果提取失败，截取前50个字符，前50字符包含标题，匹配机率较大
        extract_key_words = essay_title + "," + text[:50] if essay_title  else text[:50]

    return  extract_key_words


def parse_classify_to_metadata(classify):
    """
    将classify字符串解析为metadata数据结构
    支持格式：分类1$$描述1;分类2$$描述2;分类3;分类4$$描述4
    """
    metadata = []

    # 按分号分割各个分类项
    items = classify.split(';')

    for item in items:
        item = item.strip()
        if not item:
            continue

        # 检查是否包含$$分隔符
        if '$$' in item:
            parts = item.split('$$', 1)  # 只分割第一个$$
            cls = parts[0].strip()
            desc = parts[1].strip()
        else:
            # 没有描述信息
            cls = item
            desc = ""

        metadata.append({
            "cls": cls,
            "desc": desc
        })
    return metadata


def to_classify_new(ext_key_words, classify, is_multi):
    # 构建metadatas数据
    metadatas = parse_classify_to_metadata(classify)

    all_class = [metadata['cls'] for metadata in metadatas]
    logger.info(f"分类列表为: {all_class}")

    essay_classify_prompt = f"""
        你是一个专业的学术论文分类专家，请根据论文关键词和给定分类列表进行精准匹配。

        输入信息：
        - 论文关键词（第一个为标题）：{ext_key_words}
        - 可选分类列表：{all_class}
        
        任务要求：
        1. 仔细分析关键词与各分类的相关性
        2. 选择3-5个最相关的分类
        3. 按相关性强弱排序
        4. 严格去重，不能重复选择
        5. 只输出分类名称，用逗号分隔
        6. 没有匹配的分类，请严格输出空字符串
        
        输出格式示例：
        机器学习,神经网络,TCP协议,微服务架构,API接口
        
        请开始分析并输出结果：
    """
    cates = llm.generate_response(essay_classify_prompt)
    logger.info(f"分类结果为：'{cates}'")

    # 修改这里的处理逻辑
    if not cates or cates.strip() == '""' or cates.strip() == "''":
        # 如果没有分类结果，直接返回空字符串
        return ""

    # 返回分类结果
    if is_multi == 0:
        # 返回第一个分类
        if cates and isinstance(cates, str):
            # 按逗号分割并返回第一个分类
            categories = [cat.strip() for cat in cates.split(',') if cat.strip()]
            return categories[0] if categories else ""
        else:
            return ""
    else:
        # 直接返回模型输出的逗号分隔字符串
        return cates if cates and isinstance(cates, str) else ""
